package pseudoAssemblerCompiler.twopassassembler.view.firstpass.codeoperationtable;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pseudoAssemblerCompiler.twopassassembler.controller.AbstractController;
import pseudoAssemblerCompiler.twopassassembler.controller.OperationCodeController;
import pseudoAssemblerCompiler.twopassassembler.model.codeoperationtable.OperationCodeContentProvider;
import pseudoAssemblerCompiler.twopassassembler.model.codeoperationtable.OperationCodeLabelProvider;
import pseudoAssemblerCompiler.twopassassembler.view.common.IView;
import pseudoAssemblerCompiler.twopassassembler.view.common.ImageCache;
import pseudoAssemblerCompiler.twopassassembler.view.util.CTabFolderContainer;
import pseudoAssemblerCompiler.twopassassembler.view.util.TableViewerContainer;
import pseudoAssemblerCompiler.twopassassembler.view.util.ToolBarContainer;

import java.util.List;

/**
 * Контейнер с таблицей кодов операций
 *
 * @author Чекашов Р. И.
 */
public class CodeOperationTableImpl implements IView, ICodeOperationTableView {

    public static final Logger LOGGER =
            LoggerFactory.getLogger(CodeOperationTableImpl.class);

    /**
     * Вкладка Таблица кодов операций
     */
    private CTabItem _codeOperationTabItem;

    /**
     * Таблица кодов операций
     */
    private TableViewer _opCodeTableViewer;

    /**
     * МКОП
     */
    private TableColumn _mnemonicCodeColumn;

    /**
     * Двоичный код
     */
    private TableColumn _binaryCodeColumn;

    /**
     * Длина команды
     */
    private TableColumn _commandLengthColumn;

    /**
     * Тип адресации
     */
    private TableColumn _addressingTypeColumn;

    /**
     * Директива
     */
    private TableColumn _directiveColumn;

    /**
     * Основной контейнер для таблицы
     */
    private Composite _composite;

    private Composite _buttonsComposite;

    private Composite _tableComposite;

    private OperationCodeController _controller;

    public static final String MNEMONIC_CODE = "МКОП";

    public static final String BINARY_CODE = "Двоичный код";

    public static final String LENGTH_OF_COMMAND = "Длина команды";

    public static final String TYPE_OF_ADDRESSING = "Тип адресации";

    public static final String DIRECTIVE = "Директива";

    public static final String[] PROPS = {MNEMONIC_CODE, BINARY_CODE,
            LENGTH_OF_COMMAND, TYPE_OF_ADDRESSING, DIRECTIVE};

    /**
     * Название таблицы
     */
    private static final String TABLE_NAME = "Таблица кодов операций";

    /**
     * Создать новый код операции
     */
//    private Button _newCodeOperation;

    /**
     * Удалить код операции
     */
//    private Button _deleteCodeOperation;

    private ToolBarContainer toolBarButtons;

    private ToolItem _load;

//    private ToolItem _add;
//
//    private ToolItem _del;

    public CodeOperationTableImpl(Composite aParent) {
        CTabFolderContainer tabFolder = new CTabFolderContainer(aParent);
        _composite = new Composite(tabFolder.createCTabItem(TABLE_NAME), SWT.NONE);
        _buttonsComposite = new Composite(_composite, SWT.NONE);
        _tableComposite = new Composite(_composite, SWT.NONE);

        TableViewerContainer container = new TableViewerContainer(_tableComposite);
        _opCodeTableViewer = container.get_tableViewer();
        _opCodeTableViewer.getTable().setHeaderVisible(true);
        _opCodeTableViewer.getTable().setLinesVisible(true);

        TableViewerColumn mnemonicCodeTVC1 = container.createColumn(MNEMONIC_CODE);
        TableViewerColumn binaryCodeTVC2 = container.createColumn(BINARY_CODE);
        TableViewerColumn commandLengthTVC3 = container.createColumn(LENGTH_OF_COMMAND);
        TableViewerColumn addressingTypeTVC3 = container.createColumn(TYPE_OF_ADDRESSING);
        TableViewerColumn directiveTVC3 = container.createColumn(DIRECTIVE);

        _mnemonicCodeColumn = mnemonicCodeTVC1.getColumn();
        _binaryCodeColumn = binaryCodeTVC2.getColumn();
        _commandLengthColumn = commandLengthTVC3.getColumn();
        _addressingTypeColumn = addressingTypeTVC3.getColumn();
        _directiveColumn = directiveTVC3.getColumn();

        _opCodeTableViewer.setContentProvider(new OperationCodeContentProvider());
        _opCodeTableViewer.setLabelProvider(new OperationCodeLabelProvider());

        toolBarButtons = new ToolBarContainer(_buttonsComposite);

//        _add = toolBarButtons.createToolItem("Добавить", ImageCache.getImage("images/document-add-32x32.png"));

        _load = toolBarButtons.createToolItem("Загрузить", ImageCache.getImage("images/document-add-32x32.png"));
//                new Image(_composite.getDisplay(),"images/document-add-32x32.png"));

//        _del = toolBarButtons.createToolItem("Удалить", ImageCache.getImage("images/document-add-32x32.png"));
//                new Image(_composite.getDisplay(),"images/document-add-32x32.png"));

        container.listeners();

    }

    /**
     * Создаём содержимое контейнера
     */
    protected void createContents() {

        // Add a button to create the new person
//        _newCodeOperation = new Button(_composite, SWT.FLAT);
//        _newCodeOperation.setText("Новый код операции");
//
//        _deleteCodeOperation = new Button(_composite, SWT.FLAT);
//        _deleteCodeOperation.setText("Удалить код операции");
/*
        // Add a button to create the new person
        _newCodeOperation = new Button(_composite, SWT.PUSH);
        _newCodeOperation.setText("Новый код операции");

        _deleteCodeOperation = new Button(_composite, SWT.PUSH);
        _deleteCodeOperation.setText("Удалить код операции");
        _deleteCodeOperation.setEnabled(false);

        // Add the TableViewer
        _operationCodeTable.setContentProvider(new OperationCodeContentProvider());
        _operationCodeTable.setLabelProvider(new OperationCodeLabelProvider());

        // Set up the table
        Table table = _operationCodeTable.getTable();
        table.setLayoutData(new GridData(GridData.FILL_BOTH));

        new TableColumn(table, SWT.CENTER).setText(MNEMONIC_CODE);
        new TableColumn(table, SWT.CENTER).setText(BINARY_CODE);
        new TableColumn(table, SWT.CENTER).setText(LENGTH_OF_COMMAND);
        new TableColumn(table, SWT.CENTER).setText(TYPE_OF_ADDRESSING);
        new TableColumn(table, SWT.CENTER).setText(DIRECTIVE);

        for (int i = 0, n = table.getColumnCount(); i < n; i++) {
            table.getColumn(i).pack();
        }

        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        String[] binaryCodes = new String[256];
        for (int i = 0; i < 256; i++) {
            binaryCodes[i] = Integer.toHexString(i);
        }
        String[] lengthOfCommand = new String[] {"0", "1", "2", "3", "4"};

        String[] typeOfAddressing = new String[] {"0", "1"};

        // Create the cell editors
        CellEditor[] editors = new CellEditor[5];
        editors[0] = new TextCellEditor(table);
        editors[1] = new ComboBoxCellEditor(table, binaryCodes,
                SWT.READ_ONLY);
        editors[2] = new ComboBoxCellEditor(table, lengthOfCommand,
                SWT.READ_ONLY);
        editors[3] = new ComboBoxCellEditor(table, typeOfAddressing,
                SWT.READ_ONLY);
        editors[4] = new CheckboxCellEditor(table);

        _operationCodeTable.setColumnProperties(PROPS);
        _operationCodeTable.setCellModifier(new CodeOperationCellModifier(_operationCodeTable));
        _operationCodeTable.setCellEditors(editors);

        _operationCodeTable.setInput(_controller.getCodeOperationTableElements());*/
    }

    /**
     * Располагаем элементы в определённом порядке
     */
    protected void layouts() {
        FormData formData;
        //Temporary
        formData = new FormData();
        formData.left = new FormAttachment(0, 0);
        formData.top = new FormAttachment(0, 0);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(100, 0);
        _composite.setLayout(new FormLayout());
        _composite.setLayoutData(formData);

        formData = new FormData();
        formData.left = new FormAttachment(0, 0);
        formData.top = new FormAttachment(0, 0);
//        formData.right = new FormAttachment(100, 0);
//        formData.bottom = new FormAttachment(100, 0);
        formData.height = 60;
        _buttonsComposite.setLayout(new FormLayout());
        _buttonsComposite.setLayoutData(formData);

        formData = new FormData();
        formData.left = new FormAttachment(0, 0);
        formData.top = new FormAttachment(_buttonsComposite, 0);
        formData.right = new FormAttachment(100, 0);
        formData.bottom = new FormAttachment(100, 0);
        _tableComposite.setLayout(new FormLayout());
        _tableComposite.setLayoutData(formData);
    }

    protected void listeners() {
//        _add.addSelectionListener(new SelectionAdapter() {
//            @Override
//            public void widgetSelected(SelectionEvent e) {
//                _controller.addCodeOperation();
//            }
//        });

        _load.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                _controller.loadCodeOperationTable();
            }
        });
//
//        // Добавить новый код или директиву при нажатии на кнопку
//        _newCodeOperation.addSelectionListener(new SelectionAdapter() {
//            public void widgetSelected(SelectionEvent event) {
//                OperationCode code = new OperationCode();
//                code.set_mnemonicCode(MNEMONIC_CODE);
//                code.set_binaryCode(0);
//                code.set_lengthOfCommand(4);
//                code.set_typeOfAddressing(0);
//                code.set_directive(false);
//                _controller.getCodeOperationTableElements().put(code.get_mnemonicCode(), code);
//            }
//        });
//
//        // Добавить новый код или директиву при нажатии на кнопку
//        _deleteCodeOperation.addSelectionListener(new SelectionAdapter() {
//            public void widgetSelected(SelectionEvent event) {
//                /*OperationCode code = new OperationCode();
//                code.set_mnemonicCode(MNEMONIC_CODE);
//                code.set_binaryCode(0);
//                code.set_lengthOfCommand(4);
//                code.set_typeOfAddressing(0);
//                code.set_directive(false);
//                _controller.getCodeOperationTableElements().add(code);
//                _operationCodeTable.refresh();*/
//            }
//        });

//        _operationCodeTable.getTable().addSelectionListener(new SelectionListener() {
//            @Override
//            public void widgetSelected(SelectionEvent selectionEvent) {
//                _deleteCodeOperation.setEnabled(true);
//                OperationCode operationCode = (OperationCode) _operationCodeTable.getTable().getSelection()[0].getData();
//                LOGGER.info("Выбран код операции " + operationCode.get_mnemonicCode());
//            }
//
//            @Override
//            public void widgetDefaultSelected(SelectionEvent selectionEvent) {
//                //nothing to do
//            }
//        });
    }

    public void setController(List<AbstractController> controllers) {
        for (AbstractController abstractController : controllers) {
            if (abstractController instanceof OperationCodeController) {
                _controller = (OperationCodeController) abstractController;
                LOGGER.info("Контроллер был инициализирован.");
                return;
            }
            LOGGER.error("Контроллер не был найден в списке List<AbstractController> controllers");
        }
    }

    @Override
    public void setLayoutData(Object layoutData) {
        _composite.setLayoutData(layoutData);
    }

    @Override
    public void show() {
        layouts();
    }

    @Override
    public Composite getComposite() {
        return _composite;
    }

    @Override
    public void setController(Object controller) {
        if (controller instanceof OperationCodeController) {
            _controller = (OperationCodeController) controller;
            listeners();
            LOGGER.debug("Контроллер был инициализирован: {}", controller);
        } else {
            LOGGER.error("Контроллер не подходит этому представлению: {}", controller, this);
        }
    }

    @Override
    public void setInput(Object input) {
        _opCodeTableViewer.setInput(input);
    }

}
